using Godot;
using System;
using System.Collections.Generic;
using System.Linq;

namespace AndroidUnevenRoadGame.Game
{
	/// <summary>
	/// 游戏全局入口，负责保存当前运行状态与核心系统引用。
	/// 在 Godot 中应配置为 Autoload 单例。
	/// </summary>
	public partial class GameRoot : Node
	{
		public static GameRoot Instance { get; private set; } = null!;

		public enum GameState
		{
			MainMenu,
			Map,
			Battle,
			Event,
			Hanfu,
			Shop,
			Victory,
			Defeat
		}

		public GameState CurrentState { get; private set; } = GameState.MainMenu;
		public string SelectedCharacterId { get; private set; } = string.Empty;
		public PlayerState Player { get; private set; } = new PlayerState();
		public BattleManager BattleManager { get; private set; } = null!;
		public EventManager EventManager { get; private set; } = null!;
		public MapSystem MapSystem { get; private set; } = null!;
		public RandomNumberGenerator Random { get; } = new RandomNumberGenerator();

		public uint CurrentSeed { get; private set; } = 0;
		public int CurrentFloor { get; private set; } = 1;
		public int MaxFloor { get; private set; } = 15;
		public int CurrentMapNodeIndex { get; private set; } = 0;
		public Dictionary<int, int> SelectedMapNodes { get; } = new();

		public List<string> PlayerRelics { get; } = new();
		public List<string> PlayerPotions { get; } = new();
		public int PlayerGold { get; private set; }
		private readonly List<ShopOffer> _shopOffers = new();
		public IReadOnlyList<ShopOffer> CurrentShopOffers => _shopOffers;

		public override void _EnterTree()
		{
			if (Instance != null)
			{
				GD.PushError("GameRoot 已存在多个实例。");
				QueueFree();
				return;
			}

			Instance = this;
			Random.Seed = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

			CharacterDatabase.LoadFromJson("res://Resources/Characters/characters.json");
			CardDatabase.LoadFromJson("res://Resources/Cards/cards.json");
			EnemyDatabase.LoadFromJson("res://Resources/Enemies/enemies.json");
			PotionDatabase.LoadFromJson("res://Resources/Potions/potions.json");
			RelicDatabase.LoadFromJson("res://Resources/Relics/relics.json");

			MapSystem = new MapSystem(Random);
			BattleManager = new BattleManager(this);
			EventManager = new EventManager(this);
		}

		public override void _ExitTree()
		{
			if (Instance == this)
			{
				Instance = null!;
			}
		}

		public void StartNewRun(string characterId, uint? seed = null)
		{
			SelectedCharacterId = characterId;
			CurrentSeed = seed ?? GenerateSeed();
			Random.Seed = CurrentSeed;

			Player.Initialize(CharacterDatabase.Get(characterId));
			PlayerRelics.Clear();
			PlayerPotions.Clear();
			PlayerGold = 0;

			CurrentFloor = 1;
			CurrentMapNodeIndex = 0;
			SelectedMapNodes.Clear();
			MapSystem.GenerateFloors(CurrentSeed, MaxFloor);
			ChangeState(GameState.Map);
		}

		public void ChangeState(GameState state)
		{
			if (CurrentState == state)
			{
				EmitSignal(SignalName.StateChanged, (int)state);
				return;
			}

			CurrentState = state;
			LoadSceneForState(state);
			EmitSignal(SignalName.StateChanged, (int)state);
		}

		public void AwardGold(int amount)
		{
			PlayerGold = Math.Max(0, PlayerGold + amount);
			EmitSignal(SignalName.GoldChanged, PlayerGold);
		}

		public void AdvanceFloor()
		{
			var previousFloor = CurrentFloor;
			CurrentFloor = Math.Clamp(CurrentFloor + 1, 1, MaxFloor);

			if (CurrentFloor != previousFloor)
			{
				CurrentMapNodeIndex = -1;

				// 保留旧楼层的选择记录用于展示通关状态
				if (SelectedMapNodes.TryGetValue(previousFloor, out var nodeIndex))
				{
					SelectedMapNodes[previousFloor] = nodeIndex;
				}

				// 新楼层尚未选择节点
				if (SelectedMapNodes.ContainsKey(CurrentFloor))
				{
					SelectedMapNodes.Remove(CurrentFloor);
				}
			}

			EmitSignal(SignalName.FloorChanged, CurrentFloor);
		}

		public uint GenerateSeed()
		{
			return (uint)GD.Randi();
		}

		public void SetCurrentMapNode(int floor, int nodeIndex)
		{
			CurrentMapNodeIndex = Math.Max(0, nodeIndex);
			SelectedMapNodes[floor] = CurrentMapNodeIndex;
		}

		public bool TryGetSelectedMapNode(int floor, out int nodeIndex)
		{
			return SelectedMapNodes.TryGetValue(floor, out nodeIndex);
		}

		public void GenerateShopOffers(int count = 3)
		{
			_shopOffers.Clear();
			foreach (var card in CardDatabase.GetRandomCards(count, Random))
			{
				var price = 40 + (int)(card.Cost * 10);
				_shopOffers.Add(new ShopOffer(card.Id, price));
			}
		}

		public bool TryPurchase(ShopOffer offer)
		{
			if (PlayerGold < offer.Price)
			{
				return false;
			}

			Player.AddCardToDeck(offer.CardId);
			AwardGold(-offer.Price);
			_shopOffers.Remove(offer);
			return true;
		}

		public void ClearShopOffers()
		{
			_shopOffers.Clear();
		}

		private void LoadSceneForState(GameState state)
		{
			var tree = GetTree();
			if (tree == null)
			{
				return;
			}

			var scenePath = state switch
			{
				GameState.MainMenu => "res://Scenes/MainMenu.tscn",
				GameState.Map => "res://Scenes/Map.tscn",
				GameState.Battle => "res://Scenes/Battle.tscn",
				GameState.Event => "res://Scenes/Event.tscn",
				GameState.Hanfu => "res://Scenes/Hanfu.tscn",
				GameState.Shop => "res://Scenes/Shop.tscn",
				GameState.Victory => "res://Scenes/Victory.tscn",
				GameState.Defeat => "res://Scenes/Defeat.tscn",
				_ => string.Empty
			};

			if (!string.IsNullOrEmpty(scenePath) && ResourceLoader.Exists(scenePath))
			{
				tree.ChangeSceneToFile(scenePath);
			}
			else
			{
				GD.PushWarning($"状态 {state} 尚未配置场景：{scenePath}");
			}
		}

		[Signal]
		public delegate void StateChangedEventHandler(int state);

		[Signal]
		public delegate void GoldChangedEventHandler(int gold);

		[Signal]
		public delegate void FloorChangedEventHandler(int floor);

		public sealed record ShopOffer(string CardId, int Price);
	}
}

